#include "Rational.h"
#include <cmath>
#include <sstream>
#include <iostream>
using std::stringstream;

Rational::Rational() {
    fenZi = 0;
    fenMu = 1;
}

Rational::Rational(int fenZi, int fenMu) {
    int factor = gcd(fenZi, fenMu);
    this->fenZi = ((fenMu > 0) ? 1 : -1) * fenZi / factor;
    this->fenMu = abs(fenMu) / factor;
}

Rational::Rational(int fenZi){
    this->fenZi = fenZi;
    this->fenMu = 1;
}

int Rational::getFenZi() const {
    return fenZi;
}

int Rational::getFenMu() const {
    return fenMu;
}

int Rational::gcd(int n, int d) {
    int n1 = abs(n);
    int n2 = abs(d);
    int gcd = 1;
    for (int k = 2; k <= n1 && k <= n2; k++) {
        if (n1 % k == 0 && n2 % k == 0) gcd = k;
    }
    return gcd;
}

Rational Rational::add(const Rational& secondRational) const {
    int fenZi =
        this->fenZi * secondRational.fenMu + this->fenMu * secondRational.fenZi;

    int fenMu = this->fenMu * secondRational.fenMu;
    return Rational(fenZi, fenMu);
}

Rational Rational::subtract(const Rational& secondRational) const {
    int fenZi =
        this->fenZi * secondRational.fenMu - this->fenMu * secondRational.fenZi;

    int fenMu = this->fenMu * secondRational.fenMu;
    return Rational(fenZi, fenMu);
}

Rational Rational::multiply(const Rational& secondRational) const {
    int fenZi = this->fenZi * secondRational.fenZi;
    int fenMu = this->fenMu * secondRational.fenMu;
    return Rational(fenZi, fenMu);
}

Rational Rational::divide(const Rational& secondRational) const {
    int fenZi = this->fenZi * secondRational.fenMu;
    int fenMu = this->fenMu * secondRational.fenZi;
    return Rational(fenZi, fenMu);
}

int Rational::compareTo(const Rational& secondRational) const {
    Rational tmp = subtract(secondRational);
    if (tmp.fenZi < 0) return -1;
    if (tmp.fenZi > 0) return 1;
    return 0;
}

bool Rational::equals(const Rational& secondRational) const {
    if (compareTo(secondRational) == 0) return 1;
    return 0;
}

int Rational::intValue() const {
    return fenZi / fenMu;
}

double Rational::doubleValue() const {
    return 1.0 * fenZi / fenMu;
}

string Rational::toString() const {
    stringstream ss;
    ss << fenZi;
    if(fenMu != 1) ss << "/" << fenMu;
    return ss.str();
}

bool Rational::operator<(const Rational& secondRational) const{
    if(compareTo(secondRational) < 0) return 1;
    return 0;
}

Rational Rational::operator+(const Rational& secondRational) const{
    return add(secondRational);
}

Rational Rational::operator-(const Rational& secondRational) const{
    return subtract(secondRational);
}

int& Rational::operator[](int index){
    if(index == 0){
        return this->fenZi;
    }else if(index == 1){
        return this->fenMu;
    }else {
        std::cout << "wrong" << std::endl;
        return this->fenZi;
    }
}

Rational& Rational::operator+=(const Rational& secondRational){
    *this = add(secondRational);
    return *this;
}

Rational Rational::operator-() const{
    return Rational(-fenZi, fenMu);
}

Rational& Rational::operator++(){
    fenZi += fenMu;
    return *this;
}

Rational Rational::operator++(int dummy){
    Rational tmp(fenZi, fenMu);
    fenZi += fenMu;
    return tmp;
}

// Rational:: operator double(){
//     return doubleValue();
// }

Rational::~Rational(){}


// 友元函数
ostream& operator<<(ostream& out, const Rational& rational) {
    out << rational.fenZi << "/" << rational.fenMu;
    return out;
}

istream& operator>>(istream& in, Rational& rational){
    in >> rational.fenZi;
    in >> rational.fenMu;
    return in;
}